package com.excel2json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * excel表格转成json
 *
 * @author iven.xie
 */
public class Excel2JSONHelper {
    //常亮，用作第一种模板类型，如下图
    private static final int HEADER_VALUE_TYPE_Z = 1;
    //第二种模板类型，如下图
    private static final int HEADER_VALUE_TYPE_S = 2;

    public static void main(String[] args) {
        File file = new File("请求数据2.xlsx");
        Excel2JSONHelper excelHelper = getExcel2JSONHelper();
        //字母表头为在第1行，第2种模板类型
        JSONArray jsonArray = excelHelper.readExcel(file, 0, 2);
        System.out.println(jsonArray.toString());
    }

    /**
     * 获取一个实例
     */
    private static Excel2JSONHelper getExcel2JSONHelper() {
        return new Excel2JSONHelper();
    }

    /**
     * 文件过滤
     *
     * @param file 文件
     * @return 是否文件
     */
    private boolean fileNameFilter(java.io.File file) {
        boolean endsWith = false;
        if (file != null) {
            String fileName = file.getName();
            endsWith = fileName.endsWith(".xls") || fileName.endsWith(".xlsx");
        }
        return endsWith;
    }

    /**
     * 获取表头行
     *
     * @param sheet sheet页
     * @param index 索引
     * @return 表头行
     */
    private Row getHeaderRow(Sheet sheet, int index) {
        Row headerRow = null;
        if (sheet != null) {
            headerRow = sheet.getRow(index);
        }
        return headerRow;
    }

    /**
     * 获取表格中单元格的value
     *
     * @param row       行
     * @param cellIndex 列索引
     * @param formula   公式
     * @return 表格中单元格的value
     */
    private Object getCellValue(Row row, int cellIndex, FormulaEvaluator formula) {
        Cell cell = row.getCell(cellIndex);
        if (cell != null) {
            cell.setCellType(CellType.STRING);
            switch (cell.getCellType()) {
                //String类型
                case STRING:
                    return cell.getRichStringCellValue().getString();
                //number类型
                case NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        return cell.getDateCellValue();
                    } else {
                        return cell.getNumericCellValue();
                    }
                    //boolean类型
                case BOOLEAN:
                    return cell.getBooleanCellValue();
                //公式
                case FORMULA:
                    return formula.evaluate(cell).getNumberValue();
                default:
                    return null;
            }
        }
        return null;
    }

    /**
     * 获取表头value
     *
     * @param headerRow headerRow
     * @param cellIndex 英文表头所在的行，从0开始计算哦
     * @param type      表头的类型第一种 姓名（name）英文于实体类或者数据库中的变量一致
     * @return 表头value
     */
    private String getHeaderCellValue(Row headerRow, int cellIndex, int type) {
        Cell cell = headerRow.getCell(cellIndex);
        String headerValue = null;
        if (cell != null) {
            //第一种模板类型
            if (type == HEADER_VALUE_TYPE_Z) {
                headerValue = cell.getRichStringCellValue().getString();
                int lBracket = headerValue.indexOf("（");
                int rBracket = headerValue.indexOf("）");
                if (lBracket == -1) {
                    lBracket = headerValue.indexOf("(");
                }
                if (rBracket == -1) {
                    rBracket = headerValue.indexOf(")");
                }
                headerValue = headerValue.substring(lBracket + 1, rBracket);
            } else if (type == HEADER_VALUE_TYPE_S) {
                //第二种模板类型
                cell.setCellType(CellType.STRING);
                headerValue = cell.getRichStringCellValue().getString();
            }
        }
        return headerValue;
    }

    /**
     * 读取excel表格
     *
     * @param file        excel文件
     * @param headerIndex 头行索引
     * @param headType    读取方式
     * @return json
     */
    public JSONArray readExcel(java.io.File file, int headerIndex, int headType) {
        List<Map<String, Object>> lists = Lists.newArrayList();
        if (!fileNameFilter(file)) {
            return null;
        } else {
            try {
                //加载excel表格
                Workbook wb = WorkbookFactory.create(file);
                //读取第一个sheet页
                Sheet sheet = wb.getSheetAt(0);
                if (Objects.isNull(sheet)) {
                    return null;
                }
                //读取表头行
                Row headerRow = getHeaderRow(sheet, headerIndex);
                //读取数据
                FormulaEvaluator formula = wb.getCreationHelper().createFormulaEvaluator();
                for (int r = headerIndex + 1; r <= sheet.getLastRowNum(); r++) {
                    Row dataRow = sheet.getRow(r);
                    Map<String, Object> map = new HashMap<String, Object>();
                    for (int h = 0; h < dataRow.getLastCellNum(); h++) {
                        //表头为key
                        String key = getHeaderCellValue(headerRow, h, headType);
                        //数据为value
                        Object value = getCellValue(dataRow, h, formula);
                        if (key != null && !"".equals(key) && !"null".equals(key) && value != "{}") {
                            map.put(key, value);
                        }
                    }
                    lists.add(map);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return JSONArray.parseArray(JSON.toJSONString(lists));
    }
}

